package model;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import model.enums.FlyStayType;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

public class Fly extends Model
{
	private boolean				special;
	private AirPlane			airPlane;
	private Location			currentPosition;

	private boolean				via;
	private Location			srcPosition;
	private Location			dstPosition;
	private Location			viaPosition;

	private Date				date1;
	private Date				date2;
	private Date				date3;
	private Date				date4;
	private Date				date5;
	private Date				date6;
	private Date				date7;
	private Date				date8;

	private boolean				saatsan;
	private FlyStayType			flyStayType;
	private Date				stayStart;
	private Date				stayEnd;
	private Location			stayLocation;
	private String				saatsanComment;

	/*
	 * нислэг үйлдэгдсэнийг тэмдэглэх
	 */
	private boolean				done;

	private Set<FlyEmployee>	flyEmployees		= new HashSet<FlyEmployee>();
	private Set<FlyEmployee>	flyArriveEmployees	= new HashSet<FlyEmployee>();

	public Fly()
	{

	}

	public static Fly getLastFly(Session session, Employee employee)
	{
		ArrayList<FlyEmployee> flyEmployees = FlyEmployee.getFlyEmployeeByEmployee(session, employee);
		Fly tmpLastFly = new Fly();
		int count = 0;
		for (FlyEmployee flyEmployee : flyEmployees)
		{
			if ( count == 0 )
			{
				tmpLastFly = Fly.getFlyByPk(session, flyEmployee.getFly().getId());
			}
			else
			{
				Fly fly = Fly.getFlyByPk(session, flyEmployee.getFly().getId());
				int result = tmpLastFly.getDate1().compareTo(fly.getDate1());
				if ( result < 0 )
				{
					tmpLastFly = fly;
				}
			}

		}
		return tmpLastFly;
	}

	public static Fly getFlyByPk(Session session, long pk)
	{
		Criteria criteria = session.createCriteria(Fly.class);
		Criterion criterion = Restrictions.idEq(pk);
		criteria.add(criterion);
		return (Fly) criteria.uniqueResult();
	}

	@SuppressWarnings("deprecation")
	private static Criteria getFliesCriteriaByThisMonth(Session session)
	{
		Criteria criteria = session.createCriteria(Fly.class);
		// first date of next month
		SimpleDateFormat simpleDateformatForYear = new SimpleDateFormat("yyyy");
		SimpleDateFormat simpleDateformatForMonth = new SimpleDateFormat("MM");
		Date today = new Date();
		String year = simpleDateformatForYear.format(today);
		String month = simpleDateformatForMonth.format(today);
		Date firstDateOfThisMonth = new Date(year + "/" + month + "/01 00:00:00");
		// last date of previous month
		int intPreviousMonth = Integer.parseInt(month);
		intPreviousMonth = intPreviousMonth == 1 ? 12 : intPreviousMonth - 1;
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.YEAR, Integer.parseInt(year));
		calendar.set(Calendar.MONTH, Integer.parseInt(month));
		int lastDateofMonth = calendar.getActualMaximum(Calendar.DATE);
		Date lastDateOfThisMonth = new Date(year + "/" + month + "/" + lastDateofMonth + " 23:59:59");

		Criterion criterion1 = Restrictions.ge("date1", firstDateOfThisMonth);
		Criterion criterion2 = Restrictions.le("date1", lastDateOfThisMonth);
		criteria.add(Restrictions.and(criterion1, criterion2));
		criteria.addOrder(Order.asc("date1"));
		return criteria;
	}

	@SuppressWarnings("unchecked")
	public static ArrayList<Fly> getFliesListByThisMonth(Session session)
	{
		ArrayList<Fly> flies = (ArrayList<Fly>) getFliesCriteriaByThisMonth(session).list();
		return flies;
	}

	public static Number getFliesCountByThisMonth(Session session)
	{
		return (Number) getFliesCriteriaByThisMonth(session).setProjection(Projections.rowCount()).uniqueResult();
	}

	public static String getFlyName(Session session, Fly fly, int mode, boolean berlin_go)
	{
		if ( mode == 1 )
		{
			String srcPos = Location.getLocationCode(session, fly.getSrcPosition());
			String viaPos = Location.getLocationCode(session, fly.getViaPosition());
			String dstPos = Location.getLocationCode(session, fly.getDstPosition());
			return srcPos + "-" + ((viaPos.equals("") || srcPos.equals(viaPos)) ? "" : (viaPos + "-")) + dstPos;
		}
		else if ( mode == 2 )
		{
			String flyHourMinute = getFormattedDateForHourAndMin(fly.getDate1());
			switch ((int) fly.getDstPosition().getId())
			{
				case 1:
					return "";
				case 2:
					if ( flyHourMinute.equals("08:25") )
						return "<font color=\"#80af35\">BJS</font>";
					else if ( flyHourMinute.equals("17:25") )
						return "<font color=\"#d27c62\">BJ2</font>";
					else if ( flyHourMinute.equals("21:00") )
						return "<font color=\"#d27c62\">BJ3</font>";
					else
						return "<font color=\"#80af35\">BJS</font>";
				case 3:
					if ( flyHourMinute.equals("07:50") )
						return "<font color=\"#008000\">HKG</font>";
					else if ( flyHourMinute.equals("14:55") )
						return "<font color=\"#008000\">HK2</font>";
					else
						return "<font color=\"#008000\">HKG</font>";
				case 4:
					if ( flyHourMinute.equals("08:05") )
						return "<font color=\"#efa9f9\">ICN</font>";
					else if ( flyHourMinute.equals("15:00") )
						return "<font color=\"#efa9f9\">IC2</font>";
					else
						return "<font color=\"#efa9f9\">ICN</font>";
				case 5:
					return "<font color=\"#008000\">OM 501/2</font>";
				case 6:
					return "<font color=\"#008000\">OM 505/6</font>";
				case 7:
					return "<font color=\"#008000\">OM 137/8</font>";
				case 8:
					if ( berlin_go )
						return "<font color=\"#6ec7cb\">135</font>";
					else
						return "<font color=\"#6ec7cb\">136</font>";
				default:
					return "";
			}
		}
		else
		{
			return "";
		}
	}

	public static float getFlyDuringTime(Session session, Fly fly)
	{
		// Criteria locationCriteria = session.createCriteria(Location.class);
		// Criterion locationCriterion =
		// Restrictions.idEq(fly.getDstPosition().getId());
		// locationCriteria.add(locationCriterion);
		// Location location = (Location) locationCriteria.uniqueResult();
		// return location.getFlyTime();
		if ( fly.isVia() )
		{
			float diff1 = Employee.getDateDifference(fly.getDate1(), fly.getDate4());
			float diff2 = Employee.getDateDifference(fly.getDate5(), fly.getDate8());
			return diff1 + diff2;
		}
		else
		{
			return Employee.getDateDifference(fly.getDate1(), fly.getDate4());
		}
	}

	// public static String generatePopupS(Session session, Fly fly, String
	// rem_emp_ajax_jq_template, String add_employee_ajax_jquery_template){
	// String popup = "<div class=\"popup\" id=\"popup-"+fly.getId()+"\">";
	// popup+=generatePopupsItems(session, fly, rem_emp_ajax_jq_template);
	//
	// popup+=Employee.EmployeeAddToFlyHTMLForm(session, fly,
	// add_employee_ajax_jquery_template);
	//
	// popup+="</div>";
	// return popup;
	// }
	@SuppressWarnings("unchecked")
	public static ArrayList<Fly> getAfterFlyFromBerlinFly(Session session, Fly fly)
	{
		Criteria criteria = session.createCriteria(Fly.class);
		Criterion flyCriterion = Restrictions.gt("date1", fly.getDate1());
		criteria.add(flyCriterion);
		criteria.addOrder(Order.asc("date1"));
		criteria.setMaxResults(2);
		return (ArrayList<Fly>) criteria.list();
	}

	public static String generatePopupJQuery(Fly fly, String jqueryTemplate)
	{
		String fixJqueryTemplate = jqueryTemplate;
		fixJqueryTemplate = fixJqueryTemplate.replaceAll("\\{id\\}", fly.getId() + "");
		return fixJqueryTemplate;
	}

	@SuppressWarnings("deprecation")
	public static boolean isHourFly(Session session, int hour)
	{
		ArrayList<Fly> flies = Fly.getFliesListByThisMonth(session);
		boolean be = false;
		for (Fly fly : flies)
		{
			Date flyDate = fly.getDate1();
			int flyHour = flyDate.getHours();
			if ( flyHour == hour )
			{
				be = true;
				break;
			}
		}
		return be;
	}

	public static String checkFly(Session session, Fly fly)
	{
		String result = "";
		result += checkFlyMinMaxEmployee(session, fly);
		result += checkFlyDelayed(session,fly);
		result += checkEmployeesDelayed(session,fly);
		return result;
	}
	private static String checkFlyDelayed(Session session, Fly fly)
	{
		if (fly.isSaatsan())
			return "Саатсан";
		return "";
	}

	private static String checkEmployeesDelayed(Session session, Fly fly)
	{
		StringBuilder result = new StringBuilder();
		for (FlyEmployee flyEmployee : fly.getFlyEmployees()){
			Employee employee = flyEmployee.getEmployee();
			for (FlyEmployee flyEmployee2 : employee.getFlyEmployees()){
				Fly fly2 = flyEmployee2.getFly();
				if (fly2.isSaatsan() && fly2.getId() != fly.getId() && fly2.getDate1().getTime() < fly.getDate1().getTime()){
					result.append("<div>"+ employee.getName()+ " саатсан" +"</div>");
				}
				
			}
		}
		return result.toString();
	}

	public static String checkFlyMinMaxEmployee(Session session, Fly fly)
	{
		String result = "";
		AirPlane airPlane = fly.getAirPlane();
		Criteria flyEmployeeCriteria = session.createCriteria(FlyEmployee.class);
		Criterion flyEmployeeCriterion = Restrictions.eq("fly", fly);
		flyEmployeeCriteria.add(flyEmployeeCriterion);
		int currentEmployeeCount = flyEmployeeCriteria.list().size();
		if ( currentEmployeeCount < airPlane.getMinEmployee() )
		{
			result = "<div>Багийн гишүүд дутуу</div>";
			return result;
		}
		if ( airPlane.getMaxEmployee() < currentEmployeeCount )
		{
			result = "<div>Багийн гишүүдийн тоо хэтэрсэн</div>";
			return result;
		}
		return result;
	}

	@SuppressWarnings("unchecked")
	public static ArrayList<Fly> getFliesByEmployeeAndOrderFlyDate(Session session, Employee employee)
	{
		Criteria flyCriteria = session.createCriteria(Fly.class);
		Criteria flyEmployeeCriteria = flyCriteria.createCriteria("flyEmployees");

		Criteria employeeCriteria = flyEmployeeCriteria.createCriteria("employee");
		Criterion employeeCriterion = Restrictions.idEq(employee.getId());
		employeeCriteria.add(employeeCriterion);

		flyCriteria.addOrder(Order.asc("date1"));

		return (ArrayList<Fly>) flyCriteria.list();
	}

	public static Fly getFlyByEmployeeForThisDate(Session session, Employee employee, String date)
	{
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		ArrayList<Fly> flies = getFliesByEmployeeAndOrderFlyDate(session, employee);
		for (Fly fly : flies)
		{
			if ( sdf.format(fly.getDate1()).equals(date) )
			{
				return fly;
			}
		}
		return null;
	}

	public static String getFormattedDateForHourAndMin(Date date)
	{
		return (new SimpleDateFormat("HH:mm")).format(date);
	}

	public static Fly getLastFly(Session session)
	{
		Criteria criteria = session.createCriteria(Fly.class);
		criteria.addOrder(Order.desc("date1"));
		criteria.setMaxResults(1);
		return (Fly) criteria.uniqueResult();
	}

	public Date getArriveDate()
	{
		if ( isVia() )
		{
			return getDate8();
		}
		else
		{
			return getDate4();
		}
	}

	public Date getLeaveDate()
	{
		return getDate1();
	}

	public boolean isSpecial()
	{
		return special;
	}

	public void setSpecial(boolean special)
	{
		this.special = special;
	}

	public Set<FlyEmployee> getFlyEmployees()
	{
		return flyEmployees;
	}

	public void setFlyEmployees(Set<FlyEmployee> flyEmployees)
	{
		this.flyEmployees = flyEmployees;
	}

	public AirPlane getAirPlane()
	{
		return airPlane;
	}

	public void setAirPlane(AirPlane airPlane)
	{
		this.airPlane = airPlane;
	}

	public Location getCurrentPosition()
	{
		return currentPosition;
	}

	public void setCurrentPosition(Location currentPosition)
	{
		this.currentPosition = currentPosition;
	}

	public boolean isSaatsan()
	{
		return saatsan;
	}

	public void setSaatsan(boolean saatsan)
	{
		this.saatsan = saatsan;
	}

	public String getSaatsanComment()
	{
		return saatsanComment;
	}

	public void setSaatsanComment(String saatsanComment)
	{
		this.saatsanComment = saatsanComment;
	}

	public Location getSrcPosition()
	{
		return srcPosition;
	}

	public void setSrcPosition(Location srcPosition)
	{
		this.srcPosition = srcPosition;
	}

	public Location getDstPosition()
	{
		return dstPosition;
	}

	public void setDstPosition(Location dstPosition)
	{
		this.dstPosition = dstPosition;
	}

	public Location getViaPosition()
	{
		return viaPosition;
	}

	public void setViaPosition(Location viaPosition)
	{
		this.viaPosition = viaPosition;
	}

	public Date getDate1()
	{
		return date1;
	}

	public void setDate1(Date date1)
	{
		this.date1 = date1;
	}

	public Date getDate2()
	{
		return date2;
	}

	public void setDate2(Date date2)
	{
		this.date2 = date2;
	}

	public Date getDate3()
	{
		return date3;
	}

	public void setDate3(Date date3)
	{
		this.date3 = date3;
	}

	public Date getDate4()
	{
		return date4;
	}

	public void setDate4(Date date4)
	{
		this.date4 = date4;
	}

	public Date getDate5()
	{
		return date5;
	}

	public void setDate5(Date date5)
	{
		this.date5 = date5;
	}

	public Date getDate6()
	{
		return date6;
	}

	public void setDate6(Date date6)
	{
		this.date6 = date6;
	}

	public Date getDate7()
	{
		return date7;
	}

	public void setDate7(Date date7)
	{
		this.date7 = date7;
	}

	public Date getDate8()
	{
		return date8;
	}

	public void setDate8(Date date8)
	{
		this.date8 = date8;
	}

	public boolean isVia()
	{
		return via;
	}

	public void setVia(boolean via)
	{
		this.via = via;
	}

	public Set<FlyEmployee> getFlyArriveEmployees()
	{
		return flyArriveEmployees;
	}

	public void setFlyArriveEmployees(Set<FlyEmployee> flyArriveEmployees)
	{
		this.flyArriveEmployees = flyArriveEmployees;
	}

	public FlyStayType getFlyStayType()
	{
		return flyStayType;
	}

	public void setFlyStayType(FlyStayType flyStayType)
	{
		this.flyStayType = flyStayType;
	}

	public Date getStayStart()
	{
		return stayStart;
	}

	public void setStayStart(Date stayStart)
	{
		this.stayStart = stayStart;
	}

	public Date getStayEnd()
	{
		return stayEnd;
	}

	public void setStayEnd(Date stayEnd)
	{
		this.stayEnd = stayEnd;
	}

	public Location getStayLocation()
	{
		return stayLocation;
	}

	public void setStayLocation(Location stayLocation)
	{
		this.stayLocation = stayLocation;
	}

	public boolean isDone()
	{
		return done;
	}

	public void setDone(boolean done)
	{
		this.done = done;
	}
}
